#ifndef OLOLO_GAME_HPP
#define OLOLO_GAME_HPP

#include <list>
#include <utility>
#include <memory>
#include "falling_things.hpp"
//это такой удобный класс, который можно засунуть в список,
//или иной контейнер, а с сам класс завернуть что-нибудь 
//сложное и громоздкое
class flying_thing {
public:
	flying_thing(falling_things& ctx):m_object(ctx.create()){}
	//movable object
	flying_thing(flying_thing&& s):m_object(s.m_object){}
	flying_thing& operator =(flying_thing&& s){m_object=s.m_object;return *this;}
	
	//безопасные передавалки управления на вложенный класс
	bool out_of_screen(falling_things& ctx)
	{
		if(!m_object.get())return true;
		return m_object->out_of_screen(ctx);
	}
	void animate(falling_things& ctx, double dt)
	{if(m_object.get())m_object->animate(ctx, dt);}
	bool hit_test(falling_things& ctx, float x, float y)
	{if(m_object.get())return m_object->hit_test(ctx, x, y);else return false;}
	void paint()
	{if(m_object.get())m_object->paint();}

	~flying_thing(){}
private:
	//noncopyable object
	flying_thing(const flying_thing&);
	flying_thing& operator =(const flying_thing&);
	
	std::auto_ptr<falling_things::object> m_object;
	
};

//вот этот класс будет получать события в некоторой стандартной форме
//от кода который заведует окном, 
class game {
public:
	game(int w, int h, falling_things* gm);
	virtual ~game(){}
	//обработчики всякой фигни
	//сюда можно вставить еще обработчиков!!!
	void resize(int w, int h);//обработчик изменения размеров окна
	void mouse_motion(int x, int y);//обработчик движения мыши
	void mouse_click(int button, bool down, int x, int y);//обработчик мышетыков
	void mouse_enter(int x, int y);//на входе мыши в окно - чтоб не металась
	void paint();//отрисовка окна
	bool update_scene();//обновление сцены 
private:
	//noncopyable
	game(const game&);
	game& operator =(const game&);
	//текущий размер окна
	std::pair<int, int>		m_size;
	//предыдущее положение мыши и время движения
	std::pair<int, int> 	m_mice;
	double                  m_last_motion_time;
	//время последнего пересчета элементов
	//оно нужно нам для плавной анимации
	double 					m_last_update_time;
	//список херни на экране
	std::list<flying_thing> m_items;
	//игровое поле будет создано отдельно.
	//т.к. мы не можем пользоваться сторонними библиотеками
	//городить умные указатели для тестового задания мне влом
	//а трахаться с std::autoptr вот в этом месте еще более влом
	//будет вот такой некрасивый указатель. main() будет следить 
	//за его сохранностью
	falling_things		  * m_game_field;
};
#endif


